#include "GY_BasicsGraphicsObject.h"
#include<QDebug>
#include <QPainter>
#include <QStringList>
#include "Graphics/GY_GraphicsReflection.h"

GY_BasicsGraphicsObject::GY_BasicsGraphicsObject(const QString &guid,QGraphicsItem *pItem,QGraphicsItem *pParentItem)
    :GY_Object(guid),QGraphicsPathItem(pParentItem)
{
    //设置基类GY_Object的对象
    setpItem(pItem);
    //标记数据，key=CenterPointF(2)表示中心点位置
    GY_Object::setUserData(GY_ENUM::CenterPointF,QVariant::fromValue(centerPointF));
    //this是原版item置 0
    GY_Object::setUserData(GY_ENUM::IsCopy,QVariant::fromValue(0));
    //图形类型0控件，1容器，2组件 ,3纯数据类, 4函数类
    GY_Object::setUserData(GY_ENUM::ObjectType,QVariant::fromValue(0));
    pItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemSendsScenePositionChanges);
    pItem->setAcceptHoverEvents(true);
}

GY_Object *GY_BasicsGraphicsObject::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
//        while (iterProperty != m_PropertyInfoMap.end()) {
//            if(iterProperty.key() == "PtsArray.Capacity")
//                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
//            if(iterProperty.key() == "PtsArray.Size")
//                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
//            ++iterProperty;
//        }
//        iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QMap<QString,GY_PropertyInfo>::Iterator iter = m_PropertyInfoMap.begin();
//    while (iter != m_PropertyInfoMap.end()) {
//        if(iter.key() == "PtsArray.Capacity")
//            pObj->updateProperty(iter.key(), iter.value().propertyValue);
//        if(iter.key() == "PtsArray.Size")
//            pObj->updateProperty(iter.key(), iter.value().propertyValue);
//        ++iter;
//    }
//    iter = m_PropertyInfoMap.begin();
    while (iter != m_PropertyInfoMap.end()) {
        if(((iter.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iter.key(), submittingPropertyValues(iter.value().updateType,iter.value().propertyValue,this));
        }else if(((iter.value().updateType)&NotUpdate) == NotUpdate){
            ++iter;
            continue;
        }else {
            pObj->updateProperty(iter.key(), iter.value().propertyValue);
        }
//        qDebug()<<iter.value().propertyValue<<"============="<<iter.key()<<"------------------------------------";
        ++iter;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

bool GY_BasicsGraphicsObject::convertingBinary(const QChar &hex, QString &binary)
{
    QString num = hex;
    bool ok;
    binary = QString::number(num.toInt(&ok,16),2);
    int binaryLength = binary.length();
    for(int i=binaryLength;i<4;i++) {
        binary = '0' + binary;
    }
    return ok;
}

bool GY_BasicsGraphicsObject::getLineStyle(const QString& lineStyle, QVector<qreal>& vector)
{
    if(lineStyle.length() != 4) {
        return false;
    }
    QString binary;
    for(int i=0;i<4;i++) {
        QString temp;
        if(!convertingBinary(lineStyle.at(i),temp)) {
            vector << 1 << 0;
            return false;
        }
        binary.append(temp);
    }
    QString inversionBinary;
    for(int i=binary.length()-1;i>=0;i--) {
        inversionBinary.append(binary.at(i));
    }
    int inversionBinaryLength = inversionBinary.length();
    if(inversionBinary.at(0) == "0") {
        //0开头
        vector << 0;
        int i=0;
        bool judgment = false;
        int count = 0;
        for(;i<inversionBinaryLength;i++) {
            if((!judgment)&(inversionBinary.at(i) == "0")) {
                count++;
            }else if((!judgment)&(inversionBinary.at(i) == "1")){
                judgment = true;
                vector << count;
                count = 0;
                i--;
                continue;
            }
            if(judgment&(inversionBinary.at(i) == "1")) {
                count++;
            }else if(judgment&(inversionBinary.at(i) == "0")) {
                judgment = false;
                vector << count;
                count = 0;
                i--;
                continue;
            }
            if(i == inversionBinaryLength-1) {
                vector << count;
            }
        }
    }else if(inversionBinary.at(0) == "1"){
        //1开头
        int i=0;
        bool judgment = true;
        int count = 0;
        for(;i<inversionBinaryLength;i++) {
            if((!judgment)&(inversionBinary.at(i) == "0")) {
                count++;
            }else if((!judgment)&(inversionBinary.at(i) == "1")){
                judgment = true;
                vector << count;
                count = 0;
                i--;
                continue;
            }
            if(judgment&(inversionBinary.at(i) == "1")) {
                count++;
            }else if(judgment&(inversionBinary.at(i) == "0")) {
                judgment = false;
                vector << count;
                count = 0;
                i--;
                continue;
            }
            if(i == inversionBinaryLength-1) {
                vector << count;
            }
        }
    }
    //vector必须是偶条目if判断一下
    if(vector.count()%2) {
        vector << 0;
    }
    return true;
}

const QGradient GY_BasicsGraphicsObject::costomGradient(const QVector<qreal> &value, const qreal& fillOpacity)
{
    if(value.isEmpty())
        return QGradient();
    if(value.size() != 17 )
        return QGradient();
    m_index = value[0];
    QColor startColor(value[1],value[2],value[3],value[4]);
    startColor.setAlphaF(fillOpacity);
    QColor endColor(value[5],value[6],value[7],value[8]);
    endColor.setAlphaF(fillOpacity);
    QPointF startPoint(value[9],value[10]);
    QPointF endPoint(value[11],value[12]);
    qreal extend = value[13];
    qreal startradius = value[14];
    qreal endradius = value[15];
    qreal radial = value[16];
    if(radial == QGradient::LinearGradient) {
        QLinearGradient LGradient(startPoint,endPoint);
        LGradient.setColorAt(0, startColor);
        LGradient.setColorAt(1, endColor);
        LGradient.setSpread((QGradient::Spread)extend);
        return QGradient(LGradient);

    }
    if(radial == QGradient::RadialGradient) {
        QRadialGradient RGradient(startPoint, startradius, endPoint, endradius);
        RGradient.setColorAt(0, startColor);
        RGradient.setColorAt(1, endColor);
        RGradient.setSpread((QGradient::Spread)extend);
        return QGradient(RGradient);
    }
    return QGradient();
}

QImage GY_BasicsGraphicsObject::costomImage(const QVector<QPoint> &Transparencypoints, const QVector<QPoint> &points, const QColor value,const QImage &graImage, const QRgb graphicsViewFillColor)
{
    //继承上层属性
    QMap<QString, GY_PropertyInfo> inheritAttributes;
    if(m_PropertyInfoMap["FillAttributes"].propertyValue.toBool()) {
        //获取最上层继承属性
        inheritAttributes = getInheritAttributes("FillAttributes", this);
        //最上层继承属性为true说明不需要使用继承属性，使用原属性
        if(inheritAttributes["FillAttributes"].propertyValue.toBool() == true) {
            inheritAttributes = m_PropertyInfoMap;
        }
    }else {
        inheritAttributes = m_PropertyInfoMap;
    }
    //迭代再关联
//    QMap<QString,GY_PropertyInfo>::Iterator iter = m_PropertyInfoMap.begin();
//    while (iter != m_PropertyInfoMap.end()) {
//        iter.value().setConnect();
//        ++iter;
//    }
    QImage image;
    image.fill(graphicsViewFillColor);
    if(points.isEmpty() || (points.size() > ( 16 * 16)))
        return QImage();
    if((!inheritAttributes["FillStyle"].propertyValue.value<bool>())&&m_index) {
        image = QImage(graImage);
        int w = graImage.width();
        int h = graImage.height();
        int x = w/16+(w%16==0?0:1);
        int y = h/16+(h%16==0?0:1);
        int cx=0;
        int cy=0;
        //!16*16为一块，一块一块的与所需图案进行比较。空像素点设置透明
        for(int i=0;i<y;i++) {
            for(int j=0;j<x;j++) {
                int TransparencypointsSize = Transparencypoints.size();
                for(int k=0;k<TransparencypointsSize;k++) {
                    cx=Transparencypoints[k].x()+j*16;
                    cy=Transparencypoints[k].y()+i*16;
                    //!点xy大于wh说明超出渐变图案，不操作
                    if(cx>=w||cy>=h)
                    {
                        continue;
                    }
                    image.setPixelColor(QPoint(cx,cy), QColor(0,0,0,0));
                }
            }
        }
    }else {
        image = QImage(16, 16, QImage::Format_ARGB32);
        int pointsSize = points.size();
        for(int i{}; i < pointsSize; i++) {
            image.setPixelColor(points[i], value);
        }
        int TransparencypointsSize = Transparencypoints.size();
        for(int i{}; i < TransparencypointsSize; i++) {
            image.setPixelColor(Transparencypoints[i], QColor(0,0,0,0));
        }
    }
    return image;
}

void GY_BasicsGraphicsObject::updataPen()
{
    QPen pen = this->pen();
    if(m_PropertyInfoMap.contains("IsOpen")&&!m_PropertyInfoMap["IsOpen"].propertyValue.value<bool>()) {
        if(m_PropertyInfoMap.contains("IsOutlined")&&!m_PropertyInfoMap["IsOutlined"].propertyValue.value<bool>())
        {
            pen.setStyle(Qt::NoPen);
            this->setPen(pen);
            return;
        }
    }else if(!m_PropertyInfoMap.contains("IsOpen")) {
        if(m_PropertyInfoMap.contains("IsOutlined")&&!m_PropertyInfoMap["IsOutlined"].propertyValue.value<bool>())
        {
            pen.setStyle(Qt::NoPen);
            this->setPen(pen);
            return;
        }
    }
    //继承上层属性
    QMap<QString, GY_PropertyInfo> inheritAttributes;
    if(m_PropertyInfoMap["PenAttributes"].propertyValue.toBool()) {
        //获取最上层继承属性
        inheritAttributes = getInheritAttributes("PenAttributes", this);
        //最上层继承属性为true说明不需要使用继承属性，使用原属性
        if(inheritAttributes["PenAttributes"].propertyValue.toBool() == true) {
            inheritAttributes = m_PropertyInfoMap;
        }
    }else {
        inheritAttributes = m_PropertyInfoMap;
    }
    //迭代再关联
//    QMap<QString,GY_PropertyInfo>::Iterator iter = m_PropertyInfoMap.begin();
//    while (iter != m_PropertyInfoMap.end()) {
//        iter.value().setConnect();
//        ++iter;
//    }
    //笔的颜色
    if(m_PropertyInfoMap.contains("PenColor")) {
        QColor penColor = inheritAttributes["PenColor"].propertyValue.value<QColor>();
        if(m_PropertyInfoMap.contains("PenOpacity")) {
            penColor.setAlphaF(inheritAttributes["PenOpacity"].propertyValue.value<qreal>());
        }
        pen.setColor(penColor);
    }
    //笔的样式
    if(m_PropertyInfoMap.contains("LineStyle")) {
        LineStyle lineStyle = inheritAttributes["LineStyle"].propertyValue.value<LineStyle>();
        pen.setWidthF(lineStyle.width);
        pen.setJoinStyle(lineStyle.joinMap[lineStyle.join]);
        pen.setCapStyle(lineStyle.capMap[lineStyle.cap]);
        QVector<qreal> vector;
        if(lineStyle.line == "FFFF") {
            pen.setStyle((Qt::SolidLine));
        }else {
            getLineStyle(lineStyle.line,vector);
            pen.setDashPattern(vector);
        }
    }
    this->setPen(pen);
}

void GY_BasicsGraphicsObject::updataBrush()
{
    QBrush brush = this->brush();
    if(m_PropertyInfoMap.contains("IsOpen")&&m_PropertyInfoMap["IsOpen"].propertyValue.value<bool>())
    {
        brush.setStyle(Qt::NoBrush);
        this->setBrush(brush);
        return;
    }
    if(!m_PropertyInfoMap.contains("IsFilled")||!m_PropertyInfoMap["IsFilled"].propertyValue.value<bool>())
    {
        brush.setStyle(Qt::NoBrush);
        this->setBrush(brush);
        return;
    }

    //继承上层属性
    QMap<QString, GY_PropertyInfo> inheritAttributes;
    if(m_PropertyInfoMap["FillAttributes"].propertyValue.toBool()) {
        //获取最上层继承属性
        inheritAttributes = getInheritAttributes("FillAttributes", this);
        //最上层继承属性为true说明不需要使用继承属性，使用原属性
        if(inheritAttributes["FillAttributes"].propertyValue.toBool() == true) {
            inheritAttributes = m_PropertyInfoMap;
        }
    }else {
        inheritAttributes = m_PropertyInfoMap;
    }
    //迭代再关联
//    QMap<QString,GY_PropertyInfo>::Iterator iter = m_PropertyInfoMap.begin();
//    while (iter != m_PropertyInfoMap.end()) {
//        iter.value().setConnect();
//        ++iter;
//    }
    //更改属性map容器
    QColor brushColor = inheritAttributes["FillColor"].propertyValue.value<QColor>();
    if(m_PropertyInfoMap.contains("FillOpacity")) {
        brushColor.setAlphaF(inheritAttributes["FillOpacity"].propertyValue.value<qreal>());
    }
    if(m_PropertyInfoMap.contains("Pattern")) {
        QString fillImageValue = inheritAttributes["Pattern"].propertyValue.value<QString>();
        QVector<QPoint> fillImagePoints;
        QVector<QPoint> fillImageTransparencyPoints;
        QStringList hexList = fillImageValue.split(' ');
        int hexListSize = hexList.size();
        for(int i=0;i<hexListSize;i++) {
            QString str = hexList[i];
            while (str.size() != 4) {
                str.insert(0,'0');
            }
            QString binary;
            for(int j=0;j<4;j++) {
                QString temp;
                if(!convertingBinary(str.at(j),temp)) {
                    brush.setStyle(Qt::SolidPattern);
                    brush.setColor(brushColor);
                    return;
                }
                binary.append(temp);
            }
            int binaryLength = binary.length();
            for(int k=0;k<binaryLength;k++) {
                if(binary.at(k) == "1") {
                    fillImagePoints << QPoint(i,k);
                }else {
                    fillImageTransparencyPoints << QPoint(i,k);
                }
            }
        }
        if(!fillImagePoints.isEmpty())
        {
            QPixmap pixmap(this->boundingRect().width(),this->boundingRect().height());
            QPainter painer(&pixmap);
            painer.fillRect(pixmap.rect(),costomGradient(inheritAttributes["FillGradient"].propertyValue.value<QVector<qreal>>(),
                                inheritAttributes["FillOpacity"].propertyValue.value<qreal>()));
            QImage image = costomImage(fillImageTransparencyPoints, fillImagePoints, brushColor, pixmap.toImage());
            if(!image.isNull())
            {
                brush.setTextureImage(image);
            }else {
                brush.setColor(brushColor);
                brush.setStyle(Qt::SolidPattern);
            }
        }else {
            brush.setColor(brushColor);
            brush.setStyle(Qt::SolidPattern);
        }
    }
    this->setBrush(brush);
    return;
}

bool GY_BasicsGraphicsObject::updatePenColor(const QString &, const QVariant &value)
{
    if(!value.canConvert<QColor>())
        return false;
    QColor color= value.value<QColor>();
    m_PropertyInfoMap["PenColor"].propertyValue = color;
    updataPen();
    return true;
}

bool GY_BasicsGraphicsObject::updatePenOpacity(const QString &, const QVariant &value)
{
    if(!value.canConvert<qreal>())
        return false;
    qreal dvalue = value.value<qreal>();
    if(dvalue > 1 && dvalue < 0)
        return false;
    m_PropertyInfoMap["PenOpacity"].propertyValue = dvalue;
    updataPen();
    return true;
}

bool GY_BasicsGraphicsObject::updatePenAttributes(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
        return false;
    m_PropertyInfoMap["PenAttributes"].propertyValue = value;
    updataPen();
    return true;
}

bool GY_BasicsGraphicsObject::updateLineStyle(const QString &, const QVariant &value)
{
    if(!value.canConvert<LineStyle>())
        return false;
    m_PropertyInfoMap["LineStyle"].propertyValue = value;
    updataPen();
    return true;
}

bool GY_BasicsGraphicsObject::updateIsFilled(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
        return false;
    bool isFilled = value.value<bool>();
    m_PropertyInfoMap["IsFilled"].propertyValue = isFilled;
    updataBrush();
    return true;
}

bool GY_BasicsGraphicsObject::updateFillColor(const QString &, const QVariant &value)
{
    if(!value.canConvert<QColor>())
        return false;
    QColor color = value.value<QColor>();
    m_PropertyInfoMap["FillColor"].propertyValue = color;
    updataBrush();
    return true;
}

bool GY_BasicsGraphicsObject::updateFillGradient(const QString &, const QVariant &value)
{
    if(!value.canConvert<QVector<qreal>>())
        return false;
    m_PropertyInfoMap["FillGradient"].propertyValue = value;
    updataBrush();
    return true;
}

bool GY_BasicsGraphicsObject::updateFillStyle(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
        return false;
    bool isSolidColor = value.value<bool>();
    m_PropertyInfoMap["FillStyle"].propertyValue = isSolidColor;
    updataBrush();
    return true;
}

bool GY_BasicsGraphicsObject::updatePattern(const QString &, const QVariant &value)
{
    if(!value.canConvert<QString>())
        return false;
    m_PropertyInfoMap["Pattern"].propertyValue = value;
    updataBrush();
    return true;
}

bool GY_BasicsGraphicsObject::updateFillOpacity(const QString &, const QVariant &value)
{
    if(!value.canConvert<qreal>())
        return false;
    qreal dvalue = value.value<qreal>();
    if(dvalue > 1 && dvalue < 0)
        return false;
    m_PropertyInfoMap["FillOpacity"].propertyValue = value;
    updataBrush();
    return true;
}

bool GY_BasicsGraphicsObject::updateFillAttributes(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
        return false;
    m_PropertyInfoMap["FillAttributes"].propertyValue = value;
    updataBrush();
    return true;
}

bool GY_BasicsGraphicsObject::updateIsOpen(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
        return false;
    bool isOpen = value.value<bool>();
    m_PropertyInfoMap["IsOpen"].propertyValue = isOpen;
    updataPen();
    updataBrush();
    emit updateDrawSig();
    return true;
}

bool GY_BasicsGraphicsObject::updateIsVisible(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    bool isVisible = value.value<bool>();
    m_PropertyInfoMap["IsVisible"].propertyValue = isVisible;
    setVisible(isVisible);
    return true;
}

bool GY_BasicsGraphicsObject::updateIsAntialiased(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
        return false;
    bool isAntialiased = value.value<bool>();
    m_PropertyInfoMap["IsAntialiased"].propertyValue = isAntialiased;
    return true;
}

bool GY_BasicsGraphicsObject::updateIsOutLined(const QString &, const QVariant &value)
{
    if(!value.canConvert<bool>())
        return false;
    bool isFilled = value.value<bool>();
    m_PropertyInfoMap["IsOutlined"].propertyValue = isFilled;
    updataPen();
    return true;
}

void GY_BasicsGraphicsObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    if(m_PropertyInfoMap.contains("IsAntialiased")&&m_PropertyInfoMap["IsAntialiased"].propertyValue.toBool()) {
        painter->setRenderHint(QPainter::Antialiasing, true);
    }
    painter->setPen(this->pen());
    painter->setBrush(this->brush());
    painter->drawPath(this->path());
    QGraphicsPathItem::paint(painter,option,widget);
}

QVariant GY_BasicsGraphicsObject::itemChange(GraphicsItemChange change, const QVariant &value)
{
    //ItemPositionHasChanged
    if(change==ItemPositionChange)
    {
        QMap<QString,GY_PropertyInfo>::Iterator iter = m_PropertyInfoMap.begin();
        while (iter != m_PropertyInfoMap.end()) {
            if((iter.value().updateType&MoveUpdate) == MoveUpdate) {
                emit this->updatePropertyEvent(this,iter.value().propertyName,
                                               this->submittingPropertyValues(iter.value().updateType,
                                                                              iter.value().propertyValue,this->getGraphicsItem()),iter.value().propertyType);
            }
            ++iter;
        }
    }
    else if(change==ItemSceneHasChanged) {
        emit itemRectChange();
    }
    return QGraphicsPathItem::itemChange(change,value);
}




